home *** CD-ROM | disk | FTP | other *** search
/ Aminet 48 / Aminet 48 (2002)(GTI - Schatztruhe)[!][Apr 2002].iso / Aminet / util / conv / Wav2Cas.lha / Wav2Cas.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-02-18  |  57.7 KB  |  1,670 lines

  1. /*****************************************************************************
  2. **
  3. **  Copyright 1996, 1997 by Ernest R. Schreurs.
  4. **  All rights reserved.
  5. **  Use of this source code is allowed under the following conditions:
  6. **  You must inform people that you based your work on this stuff.
  7. **  If you charge a fee in any form for your product, you must inform people
  8. **  that this stuff is available free of charge.
  9. **  Refer to the documentation for more information.
  10. **
  11. *****************************************************************************/
  12. #define MODULE  "WAV2CAS.C"
  13. /*****************************************************************************
  14. **  NAME: WAV2CAS.C
  15. **
  16. **  Author            : Ernest R. Schreurs
  17. **  Date              : May 1, 1997
  18. **  Release           : 01.00
  19. **
  20. **  Description       : This program will convert a .wav sound file to
  21. **                      a format known as the .cas format.  It is assumed
  22. **                      that the wav file contains a sample of a Classic Atari
  23. **                      cassette tape.  This program converts the FSK sounds to
  24. **                      the data they are representing.
  25. **
  26. **  Amiga port by Wojciech Pasiecznik (voydial@wp.pl), Feb. 14, 2002.
  27. **  Few additional changes:
  28. **
  29. ** - Control Z check is replaced by the Control C (including comments),
  30. ** - title is a little changed ;).
  31. **
  32. *****************************************************************************/
  33.  
  34. /*****************************************************************************
  35. ==  INCLUDE FILES
  36. *****************************************************************************/
  37. #include <stdio.h>              /* For printf() and gets()              */
  38. #include <ctype.h>              /* For isalnum() and toupper()          */
  39. #include <stdlib.h>             /* For the exit function                */
  40. #include <string.h>             /* String and memory stuff              */
  41.  
  42. /*****************************************************************************
  43. ==  DEFINED SYMBOLS
  44. *****************************************************************************/
  45.  
  46. #ifndef FALSE
  47. #define FALSE               0
  48. #endif
  49. #ifndef TRUE
  50. #define TRUE                1
  51. #endif
  52.  
  53. #ifndef NULL
  54. #define NULL                0
  55. #endif
  56. #define PATH_LEN            128             /* Maximum path length          */
  57.  
  58. #define BUF_LEN             80              /* fgets buffer length          */
  59. #define SUCCESS             1               /* Success is non-zero          */
  60. #define FAILURE             0               /* Failure is zero              */
  61.  
  62. /*
  63. **  The PCM data is read from the wave file into a PCM buffer.
  64. **  The size of the buffer that is allocated is equal to the value defined
  65. **  below.  It must be an even value.  The buffer is replenished when half
  66. **  of the buffer is empty.  Therefore we also need to know what half of
  67. **  the buffer size is.  Make sure these values agree, if changing one,
  68. **  always change the other too.
  69. */
  70. #define PCM_BUF_LEN         512             /* Size of PCM data buffer      */
  71. #define PCM_BUF_HALF        256             /* Exactly half of above value  */
  72. #define SAMPLE_CNT_TBL_LEN  3000L           /* Size of sample count table   */
  73.  
  74. /*
  75. **  A tape record starts with a Pre-Record Write Tone.
  76. **  Then we find bytes, usually 132, each starting with a startbit,
  77. **  eight data bits, lsb first, followed by a stopbit.
  78. **  This is all coded in mark and space tones, as defined below.
  79. */
  80. #define FSK_MARK            1               /* Mark tone represents a 1     */
  81. #define FSK_SPACE           0               /* Space tone represents a 0    */
  82. #define FSK_1               1               /* A 1 bit is a mark            */
  83. #define FSK_0               0               /* A 0 bit is a space           */
  84. #define FSK_PRWT            1               /* PRWT tone is a mark          */
  85. #define FSK_STARTBIT        0               /* Startbit is a space          */
  86. #define FSK_STOPBIT         1               /* Stopbit is a mark            */
  87.  
  88. /*
  89. **  Definitions for the mark and space tone frequencies.
  90. */
  91. #define FSK_TONE_MARK       5327            /* Frequency of mark tone       */
  92. #define FSK_TONE_SPACE      3995            /* Frequency of space tone      */
  93.  
  94. /*****************************************************************************
  95. ==  MACRO DEFINITIONS
  96. *****************************************************************************/
  97. /*
  98. **  Macro for casting stuff to requirements of stupid
  99. **  standard library functions.
  100. */
  101.  
  102. #define FGETS( buf, buf_len, file_ptr )                                 \
  103.     (void *)fgets( (char *)buf, (int)buf_len, (FILE *)file_ptr )
  104.  
  105. #define STRLEN( str )                                                   \
  106.     strlen( (const char *)(str) )
  107.  
  108. /*
  109. **  Macro for getting input from the terminal,
  110. **  allowing the user to exit with either control C or
  111. **  inputting the string ^C to indicate intention of
  112. **  terminating the program.
  113. */
  114. #define GET_BUF()                                                           \
  115. {                                                                           \
  116.     if ( FGETS( buf, BUF_LEN, stdin )  ==  NULL )                           \
  117.     {                                                                       \
  118.         printf( "Terminated by ^C\n" );                                     \
  119.         exit(0);                                                            \
  120.     }                                                                       \
  121.     if ( memcmp( buf, "^C", 2 ) == 0 || memcmp( buf, "^c", 2 ) == 0  )      \
  122.     {                                                                       \
  123.         printf( "Terminated by ^C\n" );                                     \
  124.         exit(0);                                                            \
  125.     }                                                                       \
  126. }
  127.  
  128. #define PRINT( lst )                                                        \
  129. {                                                                           \
  130.     if( diagnostics )                                                       \
  131.     {                                                                       \
  132.         printf lst;                                                         \
  133.     }                                                                       \
  134. }
  135.  
  136. /*****************************************************************************
  137. ==  TYPE and STRUCTURE DEFINITIONS
  138. *****************************************************************************/
  139. typedef     unsigned char   bool;   /* Boolean value                        */
  140. typedef     unsigned char   ubyte;  /* Exactly eight bits, unsigned         */
  141. typedef     short           int16;  /* At least 16 bits, signed             */
  142. typedef     unsigned short  uint16; /* At least 16 bits, unsigned           */
  143. typedef     long            int32;  /* At least 32 bits, signed             */
  144. typedef     unsigned long   uint32; /* At least 32 bits, unsigned           */
  145.  
  146. /*
  147. **  Cassette file header.
  148. */
  149.  
  150. typedef struct
  151. {
  152.     ubyte       cas_record_id[4];       /* Cassette record type             */
  153.     ubyte       cas_len_lo;             /* Record length low byte           */
  154.     ubyte       cas_len_hi;             /* Record length high byte          */
  155.     ubyte       cas_aux1;               /* Type dependant data              */
  156.     ubyte       cas_aux2;               /* Type dependant data              */
  157.     ubyte       cas_data[8192];         /* Data                             */
  158. } cas_blk;
  159.  
  160. /*
  161. **  fsk_cnt stream.  The duration of each mark and space is counted in
  162. **  pairs, since they alternate.
  163. */
  164.  
  165. typedef struct
  166. {
  167.     uint32      sample_pos;             /* Position of sample in .wav file  */
  168.     uint32      sample_cnt_mark;        /* Number of samples in mark state  */
  169.     uint32      sample_cnt_space;       /* Number of samples in space state */
  170. } sample_cnt_blk;
  171.  
  172. /*****************************************************************************
  173. ==  IMPORTED VARIABLES
  174. *****************************************************************************/
  175. /*****************************************************************************
  176. ==  LOCAL ( HIDDEN ) VARIABLES
  177. *****************************************************************************/
  178. static FILE *   wav_file;               /* Wave file                        */
  179. static FILE *   fsk_file;               /* FSK intermediate file            */
  180. static FILE *   hex_file;               /* HEX intermediate file            */
  181. static FILE *   cas_file;               /* Cassette image file              */
  182.  
  183. static cas_blk  cas_rec;                /* The cassette record buffer       */
  184.  
  185. static uint32   cnt_cur;                /* Current period count, rounded    */
  186. static uint32   cnt_next;               /* Next period count                */
  187. static uint32   cnt_prev;               /* Previous period count            */
  188. static uint32   cnt_total;              /* Total sample count               */
  189. static uint32   cnt_val;                /* Current period actual count      */
  190.  
  191. static bool     diagnostics;            /* Print diagnostic data            */
  192. static bool     fsk;                    /* Write FSK table file             */
  193. static bool     fsk_print_first;        /* Writing FSK first line           */
  194. static uint32   sample_cnt_high;        /* High count limit for mark tone   */
  195. static uint32   sample_cnt_irg;         /* Count limit for IRG detection    */
  196. static uint32   sample_cnt_low;         /* Low count limit for mark tone    */
  197. static uint32   sample_cnt_bit;         /* Expected sample count for one bit*/
  198. static uint32   sample_cnt_bit_limit;   /* Low limit count for one bit      */
  199. static uint32   sample_cnt_minimum;     /* Minimum count for complete period*/
  200. static sample_cnt_blk * sample_cnt_tbl; /* Count table                      */
  201. static uint32   sample_tbl_ndx;         /* Count table index                */
  202. static uint16   sample_tbl_level;       /* Current level being counted      */
  203.  
  204. static ubyte    pcm[PCM_BUF_LEN];       /* Buffer with samples              */
  205. static uint32   pcm_bytes;              /* Number of bytes read into buffer */
  206. static uint32   pcm_cnt;                /* Buffer byte count                */
  207. static uint32   pcm_ck_len;             /* Length of PCM data chunk in file */
  208. static uint32   pcm_level_previous;     /* Previous sample level            */
  209. static bool     pcm_level_rising;       /* Rising / falling                 */
  210. static uint32   pcm_ndx;                /* Buffer index pointer             */
  211. static uint32   pcm_ndx_end;            /* Buffer end pointer to free space */
  212.  
  213. static uint32   printed_bytes;          /* Number of bytes printed on line  */
  214. static uint32   sample_rate;            /* Sampling rate                    */
  215.  
  216. /*****************************************************************************
  217. ==  EXPORTED VARIABLES
  218. *****************************************************************************/
  219. /*****************************************************************************
  220. ==  IMPORTED FUNCTIONS
  221. *****************************************************************************/
  222. /*****************************************************************************
  223. ==  LOCAL ( HIDDEN ) FUNCTIONS
  224. *****************************************************************************/
  225. static void     cleanup( void );
  226. static uint32   period_sample_cnt( void );
  227. static void     process_cnt( uint32 cnt, uint16 level );
  228. static uint32   process_header( void );
  229. static void     process_record( void );
  230. static void     replenish_buffer( void );
  231. static void     usage( char * cmd );
  232. static uint32   wav2fsk( void );
  233.  
  234. /*****************************************************************************
  235. ==  EXPORTED FUNCTIONS
  236. *****************************************************************************/
  237. int                 main();                 /* Normal entry point to it all */
  238.  
  239. /*****************************************************************************
  240. ==  LOCAL ( HIDDEN ) FUNCTIONS
  241. *****************************************************************************/
  242.  
  243. /*****************************************************************************
  244. **  NAME:  cleanup()
  245. **
  246. **  PURPOSE:
  247. **      Cleanup any mess that was created.
  248. **
  249. **  DESCRIPTION:
  250. **      This function will attempt to close all open files and
  251. **      free allocated memory.
  252. **
  253. **  INPUT:
  254. **      - The file pointers and paths are used.
  255. **
  256. **  OUTPUT:
  257. **      The function returns nothing.
  258. **
  259. */
  260.  
  261. static void         cleanup( void )
  262. {
  263.     if( wav_file )
  264.     {
  265.         fclose( wav_file );
  266.     }
  267.     if( fsk_file )
  268.     {
  269.         fclose( fsk_file );
  270.     }
  271.     if( hex_file )
  272.     {
  273.         fclose( hex_file );
  274.     }
  275.     if( cas_file )
  276.     {
  277.         fclose( cas_file );
  278.     }
  279.  
  280.     if( sample_cnt_tbl )
  281.         free( (void *)sample_cnt_tbl );
  282.     return;
  283. }
  284.  
  285. /*****************************************************************************
  286. **  NAME:  period_sample_cnt()
  287. **
  288. **  PURPOSE:
  289. **      Count the number of samples within one period.
  290. **
  291. **  DESCRIPTION:
  292. **      This function will count the samples between two period tops.
  293. **
  294. **  INPUT:
  295. **      Nothing.
  296. **      Data is taken from the pcm buffer.
  297. **
  298. **  OUTPUT:
  299. **      Sets the sample count to the number of samples within one period.
  300. **      If this is zero, there are no more samples.
  301. **      Prints results.
  302. **      Returns SUCCESS if data converted successfully.
  303. **      Returns FAILURE if some error occurred.
  304. **
  305. */
  306.  
  307. static uint32       period_sample_cnt( void )
  308. {
  309.  
  310. /*
  311. **  What was the current sample count, will now be the previous value.
  312. **  What was the next sample count, will now be the current value, which
  313. **  will later be rounded by comparing it with the new previous and next
  314. **  sample counts.
  315. **  What was the actual next sample count will be recorded as the value of
  316. **  the sample counter for purposes of timing.
  317. **  Determine the count for the next sample count.
  318. */
  319.     cnt_prev = cnt_val;
  320.     cnt_cur = cnt_next;
  321.     cnt_val = cnt_next;
  322.     cnt_next = 0;
  323.  
  324.     while( pcm_bytes )
  325.     {
  326.  
  327. /*
  328. **  Replenish buffer if beyond the critical mark.
  329. */
  330.         if( pcm_ndx >= PCM_BUF_HALF )
  331.             replenish_buffer();
  332.  
  333. /*
  334. **  For better difference between mark and space, we count one complete
  335. **  period, starting at one top, until the top one period away.
  336. **  We start out with a falling level, back to rising, and when the level
  337. **  stops rising, we have counted one complete period.  In order to eliminate
  338. **  noise, the number of samples must be beyond a treshold.  This by itself
  339. **  does not eliminate noise, but it eliminates low period counts.
  340. */
  341.         if( pcm_level_rising )
  342.         {                                               /* Level rising   */
  343.             if( pcm[pcm_ndx] <= pcm_level_previous )    /* At the top?    */
  344.             {
  345.                 pcm_level_rising = FALSE;
  346.                 pcm_level_previous = 255;
  347.                 if( cnt_next > sample_cnt_minimum )     /* Is it a period?*/
  348.                     break;
  349.             }
  350.             else
  351.                 pcm_level_previous = pcm[pcm_ndx];
  352.         } /* end if level rising */
  353.         else
  354.         {                                               /* Level falling  */
  355.             if( pcm[pcm_ndx] >= pcm_level_previous )    /* At the bottom? */
  356.             {
  357.                 pcm_level_rising = TRUE;
  358.                 pcm_level_previous = 0;
  359.             }
  360.             else
  361.                 pcm_level_previous = pcm[pcm_ndx];
  362.         } /* end else if level rising */
  363.  
  364. /*
  365. **  Count the number of samples within this period.
  366. */
  367.         cnt_next++;
  368.         pcm_ndx++;
  369.         pcm_bytes--;
  370.     }
  371.  
  372. /*
  373. **  Allow for sampling timing differences.  If previous and next value
  374. **  agree, the current sample is made to be the same value.  Otherwise,
  375. **  it remains the sample count value as counted.
  376. */
  377.     if( ( cnt_val == sample_cnt_low ) && ( cnt_next >= sample_cnt_low ) )
  378.         if( cnt_prev > sample_cnt_low )
  379.             cnt_cur = sample_cnt_low + 1;
  380.     if( ( cnt_val == sample_cnt_low ) && ( cnt_next <= sample_cnt_low ) )
  381.         if( cnt_prev < sample_cnt_low )
  382.             cnt_cur = sample_cnt_low - 1;
  383.  
  384.     return( SUCCESS );
  385. }
  386.  
  387. /*****************************************************************************
  388. **  NAME:  process_cnt()
  389. **
  390. **  PURPOSE:
  391. **      The sample count is used to build a table of the duration of each
  392. **      mark and space tone.  Since this is fsk data, when one stops, the
  393. **      other starts, so they are counted in pairs.
  394. **
  395. **  DESCRIPTION:
  396. **      The samples are added to the sample count table.  When there is a
  397. **      complete record in the table, we can output it to the .cas file.
  398. **
  399. **  INPUT:
  400. **      - The number of samples to be represented.
  401. **      - The level represented by the samples.
  402. **
  403. **  OUTPUT:
  404. **      Data is added to the table.
  405. **      The function returns nothing.
  406. **
  407. */
  408.  
  409. static void         process_cnt( cnt, level )
  410. uint32  cnt;                        /* Number of samples of this level      */
  411. uint16  level;                      /* Interpreted level of signal          */
  412. {
  413.  
  414. /*
  415. **  If the level is the same as the previous level, we add the count to the
  416. **  running total.  If the level is not the same, we start a new running total.
  417. **  If the new level is a space, start counting in the space counter.  If the
  418. **  level is a mark, we must increment the buffer pointer, and then we can
  419. **  start counting in the mark counter.
  420. */
  421.  
  422.     if( level == sample_tbl_level )
  423.     {
  424.         if( level == FSK_SPACE )
  425.             sample_cnt_tbl[sample_tbl_ndx].sample_cnt_space += cnt;
  426.         else
  427.             sample_cnt_tbl[sample_tbl_ndx].sample_cnt_mark += cnt;
  428.     }
  429.     else
  430.     {
  431.         sample_tbl_level = level;
  432.         if( level == FSK_SPACE )
  433.         {
  434.             sample_cnt_tbl[sample_tbl_ndx].sample_cnt_space = cnt;
  435.  
  436. /*
  437. **  If this mark was long enough to be recognized as an IRG or PRWT,
  438. **  we can start interpreting the count values as bits and bytes.
  439. */
  440.             if( sample_cnt_tbl[sample_tbl_ndx].sample_cnt_mark > sample_cnt_irg )
  441.             {
  442.                 process_record();
  443.             }
  444.         }
  445.         else
  446.         {
  447.             if( sample_tbl_ndx == SAMPLE_CNT_TBL_LEN )  /* Table full? */
  448.                 process_record();
  449.             sample_tbl_ndx++;
  450.             sample_cnt_tbl[sample_tbl_ndx].sample_cnt_mark = cnt;
  451.             sample_cnt_tbl[sample_tbl_ndx].sample_pos = cnt_total;
  452.         }
  453.     }
  454.  
  455.     cnt_total += cnt;
  456.  
  457.     return;
  458. }
  459.  
  460. /*****************************************************************************
  461. **  NAME:  process_header()
  462. **
  463. **  PURPOSE:
  464. **      Process the data from the header of the .wav file and store
  465. **      relevant information.
  466. **
  467. **  DESCRIPTION:
  468. **      This function will read the relevant data about the .wav file
  469. **      and store it.
  470. **
  471. **  INPUT:
  472. **      Nothing.
  473. **      Data is read from the wave file.
  474. **
  475. **  OUTPUT:
  476. **      Prints results.
  477. **      Stores data related to the format and contents of the wave file.
  478. **      Returns SUCCESS if header was processed successfully.
  479. **      Returns FAILURE if some error occurred.
  480. **
  481. */
  482.  
  483. static uint32       process_header( void )
  484. {
  485.     uint16          bits_sample;            /* Sample size                  */
  486.     uint32          bytes;                  /* Number of bytes read         */
  487.     uint16          channels;               /* Number of channels           */
  488.     uint32          ck_len;                 /* Chunk length                 */
  489.     uint32          fi_len;                 /* File length                  */
  490.     uint16          fmt_tag;                /* Format tag                   */
  491.     ubyte           wav_rec[512];           /* Buffer for wave data         */
  492.  
  493. /*
  494. **  Wave files usually look like this
  495. **
  496. **  char[4] = "RIFF", long file size not including these 8 bytes,
  497. **  char[4] = "WAVE",
  498. **  char[4] = "fmt ", long wave format header size not including these 8 bytes,
  499. **  bunch of longs containing info about sample rate and such,
  500. **  char[4] = "data", long wave data size not including these 8 bytes,
  501. **  gobs of PCM data bytes.
  502. **  See below for more details.
  503. */
  504.  
  505. /*
  506. **  .WAV files should begin with RIFF, followed by the size.
  507. */
  508.     bytes = fread( (char *)wav_rec, (int)1, (int)4, wav_file );
  509.     if( ( bytes < 4 ) || memcmp( wav_rec, "RIFF", 4 ) )
  510.     {
  511.         fprintf(stderr, "\nThis is not a valid .wav file, it does not begin with \"RIFF\".\n");
  512.         return( FAILURE );
  513.     }
  514.  
  515. /*
  516. **  Get the next four bytes and convert them to an uint32 value.
  517. */
  518.     bytes = fread( (char *)wav_rec, (int)1, (int)4, wav_file );
  519.     if( bytes < 4 )
  520.     {
  521.         fprintf(stderr, "\nThis is not a valid .wav file, invalid file length.\n");
  522.         return( FAILURE );
  523.     }
  524.     fi_len = (((((((uint32)wav_rec[3]) << 8 ) + wav_rec[2] ) << 8 )
  525.               + wav_rec[1]) << 8 ) + wav_rec[0];
  526.  
  527. /*
  528. **  Next we should find the block type "WAVE".
  529. */
  530.     bytes = fread( (char *)wav_rec, (int)1, (int)4, wav_file );
  531.     if( ( bytes < 4 ) || memcmp( wav_rec, "WAVE", 4 ) )
  532.     {
  533.         fprintf(stderr, "\nThis is not a valid .wav file, it does not contain \"WAVE\".\n");
  534.         return( FAILURE );
  535.     }
  536.  
  537. /*
  538. **  Next we should find the block type "fmt ".
  539. */
  540.     bytes = fread( (char *)wav_rec, (int)1, (int)4, wav_file );
  541.     if( ( bytes < 4 ) || memcmp( wav_rec, "fmt ", 4 ) )
  542.     {
  543.         fprintf(stderr, "\nThis is not a valid .wav file, it does not contain \"fmt \".\n");
  544.         return( FAILURE );
  545.     }
  546.  
  547. /*
  548. **  Get the chunk length.
  549. */
  550.     bytes = fread( (char *)wav_rec, (int)1, (int)4, wav_file );
  551.     if( bytes < 4 )
  552.     {
  553.         fprintf(stderr, "\nThis is not a valid .wav file, invalid chunk length.\n");
  554.         return( FAILURE );
  555.     }
  556.     ck_len = (((((((uint32)wav_rec[3]) << 8 ) + wav_rec[2] ) << 8 )
  557.               + wav_rec[1]) << 8 ) + wav_rec[0];
  558.  
  559. /*
  560. **  Get the format information.
  561. */
  562.     bytes = fread( (char *)wav_rec, (int)1, (int)14, wav_file );
  563.     if( bytes < 14 )
  564.     {
  565.         fprintf(stderr, "\nThis is not a valid .wav file, invalid format data.\n");
  566.         return( FAILURE );
  567.     }
  568.  
  569.     fmt_tag = (((uint16)wav_rec[1]) << 8 ) + wav_rec[0];
  570.     channels = (((uint16)wav_rec[3]) << 8 ) + wav_rec[2];
  571.     sample_rate = (((((((uint32)wav_rec[7]) << 8 ) + wav_rec[6] ) << 8 )
  572.               + wav_rec[5]) << 8 ) + wav_rec[4];
  573.  
  574. /*
  575. **  Set sample rate related variables.
  576. */
  577.     if( sample_rate == 44100L )
  578.     {
  579.         sample_cnt_low = 10;
  580.         sample_cnt_high = 14;
  581.         sample_cnt_irg = 1000;
  582.         sample_cnt_bit = 74;
  583.         sample_cnt_bit_limit = 40;
  584.         sample_cnt_minimum = 6;
  585.     }
  586.     else
  587.     if( sample_rate == 22050 )
  588.     {
  589.         sample_cnt_low = 6;
  590.         sample_cnt_high = 7;
  591.         sample_cnt_irg = 500;
  592.         sample_cnt_bit = 37;
  593.         sample_cnt_bit_limit = 20;
  594.         sample_cnt_minimum = 3;
  595.     }
  596.     else
  597.     {
  598.         fprintf(stderr, "\nSample rates other than 22.050 and 44.100 not supported.\n");
  599.         return( FAILURE );
  600.     }
  601.  
  602.     fmt_tag = (((uint16)wav_rec[1]) << 8 ) + wav_rec[0];
  603.     if( fmt_tag != 0x0001 )
  604.     {
  605.         fprintf(stderr, "\nNot a PCM wave file, format 0x%.4x not supported.\n", fmt_tag);
  606.         return( FAILURE );
  607.     }
  608.     if( channels != 1 )
  609.     {
  610.         fprintf(stderr, "\nNot a MONO wave file, stereo and multi-channel files not supported.\n");
  611.         return( FAILURE );
  612.     }
  613.  
  614. /*
  615. **  Get the bits per sample information.
  616. */
  617.     bytes = fread( (char *)wav_rec, (int)1, (int)2, wav_file );
  618.     if( bytes < 2 )
  619.     {
  620.         fprintf(stderr, "\nThis is not a valid .wav file, invalid format data.\n");
  621.         return( FAILURE );
  622.     }
  623.  
  624.     bits_sample = (((uint16)wav_rec[1]) << 8 ) + wav_rec[0];
  625.  
  626.     if( bits_sample != 8 )
  627.     {
  628.         fprintf(stderr, "\nNot a sound file sampled at 8 bit, format not supported.\n");
  629.         return( FAILURE );
  630.     }
  631.  
  632. /*
  633. **  Next we should find the block type "data".
  634. */
  635.     bytes = fread( (char *)wav_rec, (int)1, (int)4, wav_file );
  636.     if( ( bytes < 4 ) || memcmp( wav_rec, "data", 4 ) )
  637.     {
  638.         fprintf(stderr, "\nThis is not a valid .wav file, it does not contain \"data\".\n");
  639.         return( FAILURE );
  640.     }
  641.  
  642. /*
  643. **  Get the chunk length.
  644. */
  645.     bytes = fread( (char *)wav_rec, (int)1, (int)4, wav_file );
  646.     if( bytes < 4 )
  647.     {
  648.         fprintf(stderr, "\nThis is not a valid .wav file, invalid chunk length.\n");
  649.         return( FAILURE );
  650.     }
  651.     pcm_ck_len = (((((((uint32)wav_rec[3]) << 8 ) + wav_rec[2] ) << 8 )
  652.               + wav_rec[1]) << 8 ) + wav_rec[0];
  653.  
  654.     fprintf(stderr, "\nMONO 8 bit PCM format.  Sampling rate is %lu Hz.\n", sample_rate);
  655.  
  656. /*
  657. **  Well, we finally hit the PCM sample data.
  658. **  This looks like what we wanted, so we will call this success.
  659. */
  660.  
  661.     return( SUCCESS );
  662. }
  663.  
  664. /*****************************************************************************
  665. **  NAME:  process_record()
  666. **
  667. **  PURPOSE:
  668. **      There is data in the count table.  This must now be interpreted.
  669. **      The count values are converted to the data they are representing.
  670. **
  671. **  DESCRIPTION:
  672. **      This function will take data from the count table and interpret it.
  673. **      Then this data is removed from the buffer to make room for new data.
  674. **      Data that is not processed when we leave this function is moved towards
  675. **      the start of the buffer in order to make room for the new data.
  676. **      We should get here every time a complete record has been stuffed into
  677. **      the table.
  678. **
  679. **  INPUT:
  680. **      Nothing.
  681. **      Data is taken from the sample count table.
  682. **
  683. **  OUTPUT:
  684. **      Data is output to the file.
  685. **      The table is reset to the beginning.
  686. **      The function returns nothing.
  687. **
  688. */
  689.  
  690. static void         process_record( void )
  691. {
  692.     uint32          bit_cnt;                /* Bit counter                  */
  693.     uint32          bit_len;                /* Length of one bit            */
  694.     uint32          bit_limit;              /* Length for recognizing bit   */
  695.     ubyte           byte;                   /* Byte decoded from fsk data   */
  696.     uint32          bytes;                  /* Number of bytes read         */
  697.     uint32          checksum;               /* Checksum of the record       */
  698.     uint32          cnt;                    /* Count of samples             */
  699.     uint32          cnt_sum;                /* Total sample counts for byte */
  700.     uint32          ctl_1_cnt;              /* Samples in control byte 1    */
  701.     uint32          ctl_2_cnt;              /* Samples in control byte 2    */
  702.     uint32          data_ndx;               /* Index for record data        */
  703.     uint32          ndx;                    /* Index into buffer            */
  704.     uint32          ndx_prwt;               /* end of record                */
  705.  
  706. /*
  707. **  If we only have a mark tone, this must be the leader of the tape.
  708. **  We should write out the leader to the file, but for now, we will simply
  709. **  ignore it.  It will be written with the first record.
  710. */
  711.     if( sample_tbl_ndx == 0 )
  712.         return;
  713.  
  714.     bytes = 0;
  715.  
  716.     PRINT( ("\nIn process_record() sample_tbl_ndx = %lu\n", sample_tbl_ndx) );
  717.     PRINT( ("Now cleaning up glitches.\n") );
  718.  
  719. /*
  720. **  Output the table to the FSK file and the diagnostics data.
  721. */
  722.     for( ndx = 0; ndx <= sample_tbl_ndx; ndx++ )
  723.     {
  724.         PRINT( ("ndx %lu Position %lu Mark %lu, Space %lu.\n", ndx,
  725.                 sample_cnt_tbl[ndx].sample_pos,
  726.                 sample_cnt_tbl[ndx].sample_cnt_mark,
  727.                 sample_cnt_tbl[ndx].sample_cnt_space ) );
  728.  
  729. /*
  730. **  Output the table to the FSK file.
  731. **  The last space count was not finished yet, so we will have to print that
  732. **  the next time we print the table.  The last thing we print is the
  733. **  last mark count, so do not print that the next time.  Of course all
  734. **  this is not applied for the very first and very last time we print
  735. **  the contents of the table.
  736. */
  737.         if( fsk )
  738.         {
  739.             if( ndx < sample_tbl_ndx )
  740.             {
  741.                 if( ( ndx == 0 ) && ( fsk_print_first == FALSE ) )
  742.                 {                   /* First pair of table  */
  743.                     fprintf( fsk_file, "%.5lu\n",
  744.                         sample_cnt_tbl[ndx].sample_cnt_space );
  745.                 }
  746.                 else
  747.                 {                   /* First time around or regular pair */
  748.                     fprintf( fsk_file, "%.8lu %.5lu %.5lu\n",
  749.                         sample_cnt_tbl[ndx].sample_pos,
  750.                         sample_cnt_tbl[ndx].sample_cnt_mark,
  751.                         sample_cnt_tbl[ndx].sample_cnt_space );
  752.                     fsk_print_first = FALSE;
  753.                 }
  754.             } /* end if not at end of table */
  755.             else
  756.             {                       /* Last pair in table   */
  757.                 if( cnt_cur )       /* Not yet end of file? */
  758.                 {
  759.                     fprintf( fsk_file, "%.8lu %.5lu ",
  760.                         sample_cnt_tbl[ndx].sample_pos,
  761.                         sample_cnt_tbl[ndx].sample_cnt_mark );
  762.                 }
  763.                 else
  764.                 {                   /* end of file, flush all */
  765.                     fprintf( fsk_file, "%.8lu %.5lu %.5lu\n",
  766.                         sample_cnt_tbl[ndx].sample_pos,
  767.                         sample_cnt_tbl[ndx].sample_cnt_mark,
  768.                         sample_cnt_tbl[ndx].sample_cnt_space );
  769.                 }
  770.             } /* end else if not at end of table */
  771.         } /* end if fsk data requested */
  772.     } /* end for all table entries */
  773.  
  774. /*
  775. **  If things worked the way they were designed, we should have one complete
  776. **  record in the table now.  It starts out with the Pre Record Write Tone.
  777. **  Before we start processing, first clean up glitches.
  778. **  Mark and space tones that are very short should be ignored.  We add their
  779. **  count to the preceeding count.
  780. **  Maybe we should first see how many glitches there are, possibly disposing
  781. **  of this entire record as noise in the leader or PRWT.
  782. **  Since our record should start out with a very long mark tone, we will
  783. **  assume that this first mark tone is fine.
  784. */
  785.     ndx_prwt = sample_tbl_ndx;
  786.  
  787.     for( ndx = 0; ndx < sample_tbl_ndx; )
  788.     {
  789.         if( ndx && ( sample_cnt_tbl[ndx].sample_cnt_mark > sample_cnt_irg ) )
  790.         {
  791.             ndx_prwt = ndx;
  792.             break;
  793.         }
  794.  
  795. /*
  796. **  If the current space count is too low, add it, and the next mark count to
  797. **  the current mark count, move the next space count to the current space
  798. **  count, and move up the rest of the table.
  799. **  However, if the next mark count is also too low, add this space count
  800. **  and the next mark count to the next space count.  We can do this by
  801. **  adding the next mark count and the next space count to the current space
  802. **  count, and then move up the rest of the table.
  803. */
  804.         if( sample_cnt_tbl[ndx].sample_cnt_space < sample_cnt_bit_limit )
  805.         {
  806.             if( sample_cnt_tbl[ndx + 1].sample_cnt_mark < sample_cnt_bit_limit )
  807.             {
  808.                 sample_cnt_tbl[ndx].sample_cnt_space +=
  809.                 sample_cnt_tbl[ndx + 1].sample_cnt_mark +
  810.                 sample_cnt_tbl[ndx + 1].sample_cnt_space;
  811.             }
  812.             else
  813.             {
  814.                 sample_cnt_tbl[ndx].sample_cnt_mark +=
  815.                 sample_cnt_tbl[ndx].sample_cnt_space +
  816.                 sample_cnt_tbl[ndx + 1].sample_cnt_mark;
  817.                 sample_cnt_tbl[ndx].sample_cnt_space =
  818.                 sample_cnt_tbl[ndx + 1].sample_cnt_space;
  819.             }
  820.  
  821. /*
  822. **  Move the sample counts after the next one up by one.
  823. */
  824.             if( ndx + 1 < sample_tbl_ndx )
  825.             {
  826.                 memcpy( &(sample_cnt_tbl[ndx + 1]),
  827.                         &(sample_cnt_tbl[ndx + 2]),
  828.                         (sample_tbl_ndx - ndx - 1) * sizeof(sample_cnt_blk) );
  829.             }
  830.             sample_tbl_ndx--;
  831.             ndx_prwt = sample_tbl_ndx;
  832.             continue; /* Make sure it is fine now */
  833.         }
  834.  
  835. /*
  836. **  If the next mark count is too low, add it, and the next space count to
  837. **  the current space count, and move up the rest of the table.
  838. */
  839.         if( sample_cnt_tbl[ndx + 1].sample_cnt_mark < sample_cnt_bit_limit )
  840.         {
  841.             sample_cnt_tbl[ndx].sample_cnt_space +=
  842.             sample_cnt_tbl[ndx + 1].sample_cnt_mark +
  843.             sample_cnt_tbl[ndx + 1].sample_cnt_space;
  844.  
  845. /*
  846. **  Move the sample counts after the next one up by one.
  847. */
  848.             if( ndx + 1 < sample_tbl_ndx )
  849.             {
  850.                 memcpy( &(sample_cnt_tbl[ndx + 1]),
  851.                         &(sample_cnt_tbl[ndx + 2]),
  852.                         (sample_tbl_ndx - ndx - 1) * sizeof(sample_cnt_blk) );
  853.             }
  854.             sample_tbl_ndx--;
  855.             ndx_prwt = sample_tbl_ndx;
  856.             continue; /* Make sure it is fine now */
  857.         }
  858.  
  859. /*
  860. **  This sample count is fine, move to the next one.
  861. */
  862.         ndx++;
  863.     }
  864.  
  865.     if( diagnostics )
  866.     {
  867.         printf("Done cleaning up glitches. %lu elements to process.\n", ndx_prwt);
  868.         for( ndx = 0; ndx <= ndx_prwt; ndx++ )
  869.         {
  870.             printf("ndx %lu Position %lu Mark %lu, Space %lu.\n", ndx,
  871.                 sample_cnt_tbl[ndx].sample_pos,
  872.                 sample_cnt_tbl[ndx].sample_cnt_mark,
  873.                 sample_cnt_tbl[ndx].sample_cnt_space );
  874.         }
  875.     }
  876.  
  877. /*
  878. **  The table starts with a Pre-Record Write Tone.
  879. **  A bit is about 73.5 samples if the sample rate is 44.100.
  880. **  We need 73.5 samples to form a single bit.  However, the tape
  881. **  may not be coded at 600 baud.
  882. **  We have to allow for some tolerance in the baudrate.
  883. **  We need to detect the baudrate now.
  884. **  Each record starts out with two marker bytes with a value of 0x55.
  885. **  We will use these bytes to detect the baudrate, since that is what they
  886. **  were intended to be used for.
  887. **  Note that some tapes have a weird format, in which these two marker bytes
  888. **  might not be present, so if we do not find them, we cannot be sure that
  889. **  this stuff is noise in that case.
  890. */
  891.     if( ndx_prwt < 5 )
  892.     {
  893.  
  894. /*
  895. **  Glitch in the PRWT, ignore this stuff.
  896. */
  897.         bit_len = 1;
  898.         bit_limit = bit_len * 55 / 100;
  899.     }
  900.     else
  901.     if( ndx_prwt < 10 )
  902.     {
  903.  
  904. /*
  905. **  Might be one of these weird formats, probably a couple of checksum bytes.
  906. */
  907.         bit_len = sample_cnt_bit;
  908.         bit_limit = bit_len * 55 / 100;
  909.     }
  910.     else
  911.     {
  912.  
  913. /*
  914. **  We should find the two marker bytes at the beginning of the record.
  915. **  They consist of 10 alternating bits each, so we compute the sum of the
  916. **  first 20 mark and space counts, which should be 20 bits.  If we divide
  917. **  this sum by 20, we know the length of one bit.
  918. */
  919.         ctl_1_cnt = sample_cnt_tbl[0].sample_cnt_space +
  920.                     sample_cnt_tbl[1].sample_cnt_mark  +
  921.                     sample_cnt_tbl[1].sample_cnt_space +
  922.                     sample_cnt_tbl[2].sample_cnt_mark  +
  923.                     sample_cnt_tbl[2].sample_cnt_space +
  924.                     sample_cnt_tbl[3].sample_cnt_mark  +
  925.                     sample_cnt_tbl[3].sample_cnt_space +
  926.                     sample_cnt_tbl[4].sample_cnt_mark  +
  927.                     sample_cnt_tbl[4].sample_cnt_space +
  928.                     sample_cnt_tbl[5].sample_cnt_mark;
  929.         ctl_2_cnt = sample_cnt_tbl[5].sample_cnt_space +
  930.                     sample_cnt_tbl[6].sample_cnt_mark  +
  931.                     sample_cnt_tbl[6].sample_cnt_space +
  932.                     sample_cnt_tbl[7].sample_cnt_mark  +
  933.                     sample_cnt_tbl[7].sample_cnt_space +
  934.                     sample_cnt_tbl[8].sample_cnt_mark  +
  935.                     sample_cnt_tbl[8].sample_cnt_space +
  936.                     sample_cnt_tbl[9].sample_cnt_mark  +
  937.                     sample_cnt_tbl[9].sample_cnt_space +
  938.                     sample_cnt_tbl[10].sample_cnt_mark;
  939.  
  940.         bit_len = ( ctl_1_cnt + ctl_2_cnt ) / 20;
  941.  
  942. /*
  943. **  If the bit length gets a strange value, the record probably did not
  944. **  start with two marker bytes, we will assume the default baudrate.
  945. */
  946.         if( ( bit_len <= sample_cnt_bit * 70 / 100 ) ||
  947.             ( bit_len >= sample_cnt_bit * 120 / 100 ) )
  948.             bit_len = sample_cnt_bit;
  949.         bit_limit = bit_len * 55 / 100;
  950.     }
  951.  
  952.     PRINT( ("At %.8ld bit length = %lu, baudrate = %lu.\n",
  953.                 cnt_total, bit_len, sample_rate / bit_len ) );
  954.  
  955.     if( ( bit_len > sample_cnt_bit * 70 / 100 ) &&
  956.         ( bit_len < sample_cnt_bit * 120 / 100 ) )
  957.     {
  958.         fprintf( stderr,
  959.                  "At %.8ld bit length = %lu samples, baudrate = %lu baud.\n",
  960.                  cnt_total, bit_len, sample_rate / bit_len );
  961.  
  962. /*
  963. **  Write out the data to the cassette file.
  964. **  Put the length of the PRWT into the aux-bytes.
  965. */
  966.         memcpy( cas_rec.cas_record_id, "data", 4 );
  967.         cas_rec.cas_len_lo = 0;
  968.         cas_rec.cas_len_hi = 0;
  969.         cas_rec.cas_aux1 =  (( sample_cnt_tbl[0].sample_cnt_mark * 1000 ) / sample_rate ) % 256;
  970.         cas_rec.cas_aux2 =  (( sample_cnt_tbl[0].sample_cnt_mark * 1000 ) / sample_rate ) / 256;
  971.  
  972.         data_ndx = 0;
  973.  
  974.         for( ndx = 0; ndx < ndx_prwt; )
  975.         {
  976.  
  977. /*
  978. **  A byte consists of 8 data bits, a startbit and a stopbit.
  979. **  See how many bits are represented by the sample count.
  980. */
  981.             byte = 0x00;
  982.             cnt_sum = 0;
  983.             PRINT( ("Offset %lu ndx %lu ", sample_cnt_tbl[ndx].sample_pos,
  984.                     ndx ) );
  985.             for( bit_cnt = 0; bit_cnt < 10; )
  986.             {
  987.                 cnt = sample_cnt_tbl[ndx].sample_cnt_space;
  988.                 cnt_sum += cnt;
  989.                 PRINT( (" %lu ", cnt ) );
  990.                 while( cnt > bit_limit )
  991.                 {
  992.                     if( cnt > bit_len )
  993.                         cnt -= bit_len;
  994.                     else
  995.                         cnt = 0;
  996.                     if( bit_cnt )           /* Ignore startbit */
  997.                     {
  998.                         byte = byte >> 1;   /* Make room for next bit */
  999.                         byte &= 0x7F;       /* Add a zero bit         */
  1000.                         PRINT( ("0") );
  1001.                     }
  1002.                     bit_cnt++;
  1003.                     if( bit_cnt == 10 )     /* Quit when we hit the stopbit */
  1004.                         break;
  1005.                 } /* End while processing space count */
  1006.                 ndx++;
  1007.                 cnt = sample_cnt_tbl[ndx].sample_cnt_mark;
  1008.                 cnt_sum += cnt;
  1009.                 PRINT( (" %lu ", cnt ) );
  1010.                 while( cnt > bit_limit )
  1011.                 {
  1012.                     if( cnt > bit_len )
  1013.                         cnt -= bit_len;
  1014.                     else
  1015.                         cnt = 0;
  1016.                     if( bit_cnt < 9 )       /* Ignore stopbit         */
  1017.                     {
  1018.                         byte = byte >> 1;   /* Make room for next bit */
  1019.                         byte |= 0x080;      /* Add a one bit          */
  1020.                         PRINT( ("1") );
  1021.                     }
  1022.                     bit_cnt++;
  1023.                     if( bit_cnt == 10 )     /* Quit when we hit the stopbit */
  1024.                         break;
  1025.                 } /* End while processing mark count */
  1026.             } /* End for 10 bits */
  1027.             PRINT( ("\nByte %.2x sum %lu.\n", byte, cnt_sum ) );
  1028.             cas_rec.cas_data[data_ndx++] = byte;
  1029.             bytes++;
  1030.         } /* end for all pairs up to next PRWT */
  1031.  
  1032.         cas_rec.cas_len_hi = data_ndx / 256;
  1033.         cas_rec.cas_len_lo = data_ndx % 256;
  1034.         fwrite( &cas_rec, 1,
  1035.                 cas_rec.cas_len_hi * 256 + cas_rec.cas_len_lo + 8, cas_file );
  1036.  
  1037. /*
  1038. **  Print the hex values.
  1039. **  Start out with the PRWT length and the record length.
  1040. */
  1041.         fprintf( hex_file, "%.5lu %lu",
  1042.         ( sample_cnt_tbl[0].sample_cnt_mark * 1000 ) / sample_rate, bytes );
  1043.         checksum = 0;
  1044.         for( ndx = 0; ndx < data_ndx; ndx++ )
  1045.         {
  1046.             fprintf( hex_file, " %.2x", cas_rec.cas_data[ndx] );
  1047.             if( ndx < data_ndx - 1 )
  1048.             {
  1049.                 checksum += cas_rec.cas_data[ndx];
  1050.                 if( checksum > 0x0ff )  /* If carry */
  1051.                 {
  1052.                     checksum &= 0x0ff;  /* Wrap around */
  1053.                     checksum++;         /* Add carry back in */
  1054.                 }
  1055.              }
  1056.         } /* end for all bytes in the block */
  1057.         fprintf( hex_file, " %.2lx %s\n", checksum,
  1058.                  ( checksum == cas_rec.cas_data[data_ndx - 1] ) ? "ok" : "bad" );
  1059.  
  1060.         if( diagnostics )
  1061.         {
  1062.             if( checksum != cas_rec.cas_data[data_ndx - 1] )
  1063.                 printf("\nBad checksum!\n");
  1064.             printf( "PRWT is %lu milliseconds.\n", sample_cnt_tbl[0].sample_cnt_mark / 44 );
  1065.         }
  1066.  
  1067. /*
  1068. **  Move the remaining portion of the buffer to the beginning of the buffer.
  1069. **  Cleaning up the table might have caused the PRWT to be not the last
  1070. **  element in the table, so take note of this when moving the table.
  1071. */
  1072.         if( sample_tbl_ndx )
  1073.         {
  1074.             if( sample_tbl_ndx > ndx_prwt )
  1075.             {
  1076.                 ndx = sample_tbl_ndx - ndx_prwt + 1;
  1077.                 memcpy( &(sample_cnt_tbl[0]),
  1078.                         &(sample_cnt_tbl[ndx_prwt]),
  1079.                         sizeof(sample_cnt_blk) * ndx);
  1080.                 sample_tbl_ndx = ndx - 1;
  1081.             }
  1082.             else
  1083.             {
  1084.                 memcpy( &(sample_cnt_tbl[0]),
  1085.                         &(sample_cnt_tbl[sample_tbl_ndx]),
  1086.                         sizeof(sample_cnt_blk) );
  1087.                 sample_tbl_ndx = 0;
  1088.             }
  1089.         }
  1090.     } /* end if baudrate acceptable */
  1091.     else
  1092.     {
  1093.         fprintf( stderr,
  1094.                  "At %.8ld skipping noise or bad data.\n",
  1095.                  cnt_total );
  1096.  
  1097. /*
  1098. **  Must have been noise, add it all and consider it prwt.
  1099. */
  1100.         if( sample_tbl_ndx )
  1101.         {
  1102.             for( ndx = 0; ndx < ndx_prwt; ndx++ )
  1103.             {
  1104.                 sample_cnt_tbl[ndx_prwt].sample_cnt_mark +=
  1105.                 sample_cnt_tbl[ndx].sample_cnt_mark +
  1106.                 sample_cnt_tbl[ndx].sample_cnt_space;
  1107.             }
  1108.             ndx = sample_tbl_ndx - ndx_prwt + 1;
  1109.             memcpy( &(sample_cnt_tbl[0]),
  1110.                     &(sample_cnt_tbl[ndx_prwt]),
  1111.                     sizeof(sample_cnt_blk) * ndx);
  1112.             sample_tbl_ndx = 0;
  1113.         }
  1114.     }
  1115.  
  1116.     PRINT( ("Leaving process_record() with %lu bytes processed.\n", bytes ) );
  1117.  
  1118. }
  1119.  
  1120. /*****************************************************************************
  1121. **  NAME:  replenish_buffer()
  1122. **
  1123. **  PURPOSE:
  1124. **      Keep the buffer filled with PCM data.
  1125. **
  1126. **  DESCRIPTION:
  1127. **      This function will read data from the wave file and store it in the
  1128. **      PCM buffer.  Data that was still left in the buffer is moved towards
  1129. **      the start of the buffer in order to make room for the new data.
  1130. **
  1131. **  INPUT:
  1132. **      Nothing.
  1133. **      Data is read from the wave file.
  1134. **
  1135. **  OUTPUT:
  1136. **      Data is stored in the buffer.
  1137. **      Buffer status is updated.
  1138. **      The function returns nothing.
  1139. **
  1140. */
  1141.  
  1142. static void         replenish_buffer( void )
  1143. {
  1144.     uint32          bytes;                  /* Number of bytes read         */
  1145.     uint32          rest_len;               /* Remaining bytes in buffer    */
  1146.     ubyte           wav_rec[PCM_BUF_HALF];  /* Buffer for reading wave data */
  1147.  
  1148. /*
  1149. **  Replenish buffer.
  1150. **  Move the remaining portion of the buffer to the beginning of the buffer.
  1151. **  The buffer end points to just beyond the last byte of the buffer.
  1152. */
  1153.     if( pcm_ndx && pcm_ndx_end )
  1154.     {
  1155.         if( pcm_ndx > pcm_ndx_end )
  1156.         {
  1157.             fprintf( stderr, "\nPanic: Beyond end of buffer.\n");
  1158.             getchar();
  1159.         }
  1160.         else
  1161.         {
  1162.             rest_len = pcm_ndx_end - pcm_ndx;
  1163.             memcpy( pcm, &pcm[pcm_ndx], rest_len );
  1164.             pcm_ndx = 0;
  1165.             pcm_ndx_end = rest_len;
  1166.         }
  1167.     }
  1168.  
  1169. /*
  1170. **  Get some more bytes and stuff them into the PCM buffer.
  1171. */
  1172.     bytes = PCM_BUF_HALF;
  1173.     bytes = fread( (char *)wav_rec, (int)1, (int)bytes, wav_file );
  1174.     if( bytes )
  1175.     {
  1176.         memcpy( &pcm[pcm_ndx_end], wav_rec, bytes );
  1177.         pcm_ndx_end += bytes;
  1178.         pcm_bytes += bytes;
  1179.     }
  1180. }
  1181.  
  1182. /*****************************************************************************
  1183. **  NAME:  usage()
  1184. **
  1185. **  PURPOSE:
  1186. **      Display the command line format for the program.
  1187. **
  1188. **  DESCRIPTION:
  1189. **      This function will explain the usage of the program to the user.
  1190. **      The program name is taken from the first command line argument.
  1191. **
  1192. **  INPUT:
  1193. **      - The address of the command line, containing the program name.
  1194. **
  1195. **  OUTPUT:
  1196. **      The usage is displayed on the terminal.
  1197. **      The function returns nothing.
  1198. **
  1199. */
  1200.  
  1201. static void         usage( cmd )
  1202. char * cmd;                         /* Program name                     */
  1203. {
  1204.     char * whoami;      /* For searching program name in command line   */
  1205.     char * name;        /* Pointer to actual program name in command    */
  1206.     int    len;         /* Length of program name                       */
  1207.     int    found_dot;   /* Nonzero if we found a dot in the name        */
  1208.  
  1209. /*
  1210. **  Get program name and print usage message.
  1211. **  The complete pathname including extension is part of the first
  1212. **  argument as passed by the operating system.
  1213. */
  1214.     for( whoami = cmd, len = 0, found_dot = 0; *whoami; whoami++ )
  1215.     {
  1216.         if( *whoami == '.' )
  1217.         {
  1218.             found_dot = 1;
  1219.             continue;
  1220.         }
  1221.         if( *whoami == '\\' )   /* if this was part of the path, */
  1222.         {
  1223.             name = whoami + 1;  /* record position */
  1224.             len = 0;            /* then restart counting length */
  1225.             found_dot = 0;
  1226.             continue;
  1227.         }
  1228.         if( *whoami == ' ' )    /* end of name found            */
  1229.             break;
  1230.         if( found_dot )         /* skip .exe or .com stuff      */
  1231.             continue;
  1232.         len++;                  /* Increment program name length */
  1233.     }
  1234.  
  1235. /*
  1236. **  Let me explain...
  1237. */
  1238.     fprintf(stderr, "\nUsage: %.*s [wavefile] [\"description\"] [/d] [/f]\n", len, name);
  1239.     fprintf(stderr, "to convert a .wav file to a .cas cassette image.\n\n");
  1240.     fprintf(stderr, "wavefile      an Atari classic tape sampled at 44.100.\n");
  1241.     fprintf(stderr, "description   descriptive text entered as a quoted string.\n\n");
  1242.     fprintf(stderr, "/d            to print diagnostic information.\n");
  1243.     fprintf(stderr, "/f            to write the FSK table file.\n");
  1244.     fprintf(stderr, "Refer to the documentation for more information.\n");
  1245.  
  1246.     return;
  1247. }
  1248.  
  1249. /*****************************************************************************
  1250. **  NAME:  wav2fsk()
  1251. **
  1252. **  PURPOSE:
  1253. **      Read data from the .wav file and convert it to levels recognized
  1254. **      as fsk mark and space values.
  1255. **      The number of samples within one half period is counted.  Based on
  1256. **      this, we can determine the frequency of the sound, and thus we can
  1257. **      distinguish between mark and space levels.  The output routine is
  1258. **      then called to print this number of samples.
  1259. **      The number of samples of this level are recorded for interpretation.
  1260. **      If we have a complete record in the buffer, we can try to interpret
  1261. **      the bits in the buffer.
  1262. **
  1263. **  DESCRIPTION:
  1264. **      This function will read the data and process it.
  1265. **
  1266. **  INPUT:
  1267. **      Nothing.
  1268. **
  1269. **  OUTPUT:
  1270. **      Prints results.
  1271. **      Returns SUCCESS if data converted successfully.
  1272. **      Returns FAILURE if some error occurred.
  1273. **
  1274. */
  1275.  
  1276. static uint32       wav2fsk( void )
  1277. {
  1278.     uint16          level;                  /* Interpreted level of signal  */
  1279.  
  1280.     cnt_total = 0;
  1281.  
  1282. /*
  1283. **  Set pointers to point to the end of the buffer.
  1284. */
  1285.     pcm_cnt = 0;
  1286.     pcm_ndx = 0;
  1287.     pcm_ndx_end = 0;
  1288.  
  1289. /*
  1290. **  Initialize sample count table.
  1291. */
  1292.     sample_tbl_ndx = 0;
  1293.     sample_tbl_level = FSK_MARK;
  1294.     sample_cnt_tbl[0].sample_pos = 0;
  1295.     sample_cnt_tbl[0].sample_cnt_mark = 0;
  1296.  
  1297. /*
  1298. **  Load the buffer.
  1299. */
  1300.     replenish_buffer();
  1301.     replenish_buffer();
  1302.  
  1303.     if( pcm[1] > pcm[0] )
  1304.     {
  1305.         pcm_level_previous = 0;
  1306.         pcm_level_rising = TRUE;
  1307.     }
  1308.     else
  1309.     {
  1310.         pcm_level_previous = 255;
  1311.         pcm_level_rising = FALSE;
  1312.     }
  1313.  
  1314.     period_sample_cnt();
  1315.     period_sample_cnt();
  1316.     while( cnt_cur )
  1317.     {
  1318.         if( ( cnt_cur >= sample_cnt_low ) && ( cnt_cur <= sample_cnt_high ) )
  1319.             level = FSK_SPACE;
  1320.         else
  1321.             level = FSK_MARK;
  1322.  
  1323.         process_cnt( cnt_val, level );
  1324.  
  1325.         period_sample_cnt();
  1326.     } /* end while */
  1327.     process_record();
  1328.     printf("\n");
  1329.  
  1330.     return( SUCCESS );
  1331. }
  1332.  
  1333. /*****************************************************************************
  1334. ==  EXPORTED FUNCTIONS
  1335. *****************************************************************************/
  1336.  
  1337. /*****************************************************************************
  1338. **  NAME:  MAIN()
  1339. **
  1340. **  PURPOSE:
  1341. **      An entry point for testing or running this utility.
  1342. **
  1343. **  DESCRIPTION:
  1344. **      Prompt for the file to open and then go process it.
  1345. **
  1346. **  INPUT:
  1347. **      argc and argv.
  1348. **
  1349. **  OUTPUT:
  1350. **      Returns an int as it should.
  1351. **
  1352. */
  1353. int                 main( argc, argv )
  1354. int                 argc;               /* Command line argument count  */
  1355. char              * argv[];             /* Command line argument ptrs   */
  1356. {
  1357.     ubyte           answer;                 /* Response to yes/no question  */
  1358.     uint32          arg_ndx;                /* Argument number index        */
  1359.     uint32          arg_no;                 /* Argument number              */
  1360.     uint32          wrk_ndx;                /* Work index                   */
  1361.     ubyte           desc[80];               /* Description of cassette tape */
  1362.     uint16          desc_len;               /* Length of the description    */
  1363.     bool            end_of_str;             /* Null terminator seen?        */
  1364.     ubyte           input_path[PATH_LEN];   /* Input wave file spec         */
  1365.     ubyte           fsk_path[PATH_LEN];     /* Output fsk file spec         */
  1366.     ubyte           hex_path[PATH_LEN];     /* Output hex file spec         */
  1367.     ubyte           cas_path[PATH_LEN];     /* Output cas file spec         */
  1368.     ubyte           buf[BUF_LEN];           /* Buffer string                */
  1369.     uint32          stat;                   /* Status from function         */
  1370.     ubyte           proceed;                /* Proceed with conversion      */
  1371.  
  1372. /*
  1373. **  Allocate buffer space for the sample count table.
  1374. */
  1375.     sample_cnt_tbl = (sample_cnt_blk *)
  1376.                      malloc((unsigned long)SAMPLE_CNT_TBL_LEN *
  1377.                             sizeof( sample_cnt_blk ) );
  1378.  
  1379.  
  1380.     if( !sample_cnt_tbl )
  1381.     {
  1382.         fprintf( stderr, "\nCannot allocate buffer, insufficient memory.\n" );
  1383.         exit( 255 );
  1384.     }
  1385.  
  1386. /*
  1387. **  Process command line arguments.
  1388. **  We do not treat the options switch as an argument.  It may be placed
  1389. **  anywhere on the command line.  So we have to count the arguments ourselves
  1390. **  so that we know what argument we are processing.
  1391. */
  1392.     arg_no = 0;
  1393.     diagnostics = FALSE;
  1394.     fsk = FALSE;
  1395.     desc_len = 0;
  1396.  
  1397.     for( arg_ndx = 1; arg_ndx < argc; arg_ndx++ )
  1398.     {
  1399.  
  1400. /*
  1401. **  If we encounter the options switch, process the options.
  1402. **  The options must start with a slash.
  1403. */
  1404.         if( argv[arg_ndx][0] == '/' )
  1405.         {
  1406.  
  1407.             for( wrk_ndx = 0; argv[arg_ndx][wrk_ndx]; wrk_ndx++ )
  1408.             {
  1409.  
  1410. /*
  1411. **  If the user is confused, seeking help, she/he should read the * manual.
  1412. **  We can give them a hint though.
  1413. */
  1414.                 if( argv[arg_ndx][wrk_ndx] == '?' )
  1415.                 {
  1416.                     usage( argv[0] );
  1417.                     exit( 0 );
  1418.                 }
  1419.  
  1420. /*
  1421. **  The /d option selects the diagnostics output.
  1422. */
  1423.                 if( toupper( argv[arg_ndx][wrk_ndx] ) == 'D' )
  1424.                 {
  1425.                     diagnostics = TRUE;
  1426.                     continue;
  1427.                 }
  1428.  
  1429. /*
  1430. **  The /f option selects the fsk table output.
  1431. */
  1432.                 if( toupper( argv[arg_ndx][wrk_ndx] ) == 'F' )
  1433.                 {
  1434.                     fsk = TRUE;
  1435.                     continue;
  1436.                 }
  1437.  
  1438. /*
  1439. **  Ignore other options.
  1440. */
  1441.                 continue;
  1442.             } /* end for all characters after options switch */
  1443.  
  1444. /*
  1445. **  No further processing for the options switches.
  1446. */
  1447.             continue;
  1448.         } /* end if options switch */
  1449.         arg_no++;
  1450.  
  1451. /*
  1452. **  First argument is the file spec.
  1453. */
  1454.         if( arg_no == 1 )
  1455.         {
  1456.             for ( wrk_ndx = 0, end_of_str = FALSE;
  1457.                 wrk_ndx < PATH_LEN; wrk_ndx++ )
  1458.             {
  1459.                 if ( argv[arg_ndx][wrk_ndx] == '\0' ) /* End of argument string?            */
  1460.                     end_of_str = TRUE;
  1461.                 if ( end_of_str )
  1462.                     input_path[wrk_ndx] = '\0';
  1463.                 else
  1464.                     input_path[wrk_ndx] = toupper( argv[arg_ndx][wrk_ndx] );
  1465.             }
  1466.  
  1467.             wav_file = fopen( (char *)input_path, "rb" );
  1468.             if( wav_file == NULL )
  1469.             {
  1470.                 fprintf(stderr, "Cannot open wave file %s\n", input_path);
  1471.                 exit( 255 );
  1472.             }
  1473.         }
  1474.  
  1475. /*
  1476. **  Optionally, the description can be entered as the second command line
  1477. **  argument.  This should be done as a quoted string, since that is the
  1478. **  way command line arguments work.
  1479. */
  1480.         if( arg_no ==  2 )
  1481.         {
  1482.             desc_len = STRLEN( argv[arg_ndx] );
  1483.             if( desc_len > 80 )
  1484.                 desc_len = 80;
  1485.             memcpy( desc, argv[arg_ndx], desc_len );
  1486.         } /* end if description argument */
  1487.     } /* end for all command line arguments */
  1488.  
  1489. /*
  1490. **  If there is no filename on the command line, ask for it.
  1491. */
  1492.     if( arg_no == 0 )
  1493.     {
  1494.  
  1495. /*
  1496. **  Open hailing frequencies.
  1497. **  No command line arguments, so ask what it is we have to do.
  1498. */
  1499.         printf( "Classic Atari cassette tape recovery version April 20, 1997\n" );
  1500.         printf( "Copyright 1996, 1997 by Ernest R. Schreurs. All rights reserved.\n" );
  1501.         printf( "Amiga port by Wojciech Pasiecznik (voydial@wp.pl).\n" );
  1502.  
  1503.  
  1504.         while( TRUE )                       /* until terminated by control C*/
  1505.         {
  1506.             printf( "\nEnter ^C or hit Control C to terminate\n" );
  1507.  
  1508.             do                              /* until .wav file entered    */
  1509.             {
  1510.                 printf("\nEnter .wav file to be converted : ");
  1511.                 GET_BUF();
  1512.  
  1513.                 for ( wrk_ndx = 0, end_of_str = FALSE;
  1514.                     wrk_ndx < PATH_LEN; wrk_ndx++ )
  1515.                 {
  1516.                     if ( wrk_ndx < BUF_LEN )
  1517.                     {
  1518.                         if ( buf[wrk_ndx] == '\n' ) /* End of inputted string?      */
  1519.                             end_of_str = TRUE;
  1520.                         if ( buf[wrk_ndx] == '\0' ) /* Overkill, End marked by \n   */
  1521.                             end_of_str = TRUE;
  1522.                         if ( end_of_str )
  1523.                             input_path[wrk_ndx] = '\0';
  1524.                         else
  1525.                             input_path[wrk_ndx] = toupper( buf[wrk_ndx] );
  1526.                     }
  1527.                 }
  1528.             } while ( input_path[0] == ' ' );
  1529.  
  1530.             do                              /* until answer is Y or N       */
  1531.             {
  1532.                 printf("\nLoading file %s\n", input_path);
  1533.                 printf("\nIs this correct Y)es or N)o : ");
  1534.                 GET_BUF();
  1535.                 proceed = toupper( buf[0] );
  1536.  
  1537. /*
  1538. **  If blank, default is correct
  1539. */
  1540.                 if ( proceed == '\n' )
  1541.                     proceed = 'Y';
  1542.  
  1543.             } while ( proceed != 'Y' && proceed != 'N' );
  1544.  
  1545.             if ( proceed == 'N' )
  1546.                 continue;
  1547.  
  1548.             do                              /* until answer is Y or N       */
  1549.             {
  1550.                 printf("\nPrint diagnostic data Y)es or N)o : ");
  1551.                 GET_BUF();
  1552.                 answer = toupper( buf[0] );
  1553.  
  1554. /*
  1555. **  If blank, default is correct
  1556. */
  1557.                 if ( answer == '\n' )
  1558.                     answer = 'Y';
  1559.  
  1560.             } while ( answer != 'Y' && answer != 'N' );
  1561.  
  1562.             diagnostics = ( answer == 'Y' ) ? TRUE : FALSE;
  1563.  
  1564.             printf( "\nLoading data from wave file.\n" );
  1565.  
  1566.             wav_file = fopen( (char *)input_path, "rb" );
  1567.             if( wav_file == NULL )
  1568.             {
  1569.                 fprintf(stderr, "Cannot open wave file\n");
  1570.                 continue;
  1571.             }
  1572.             break;
  1573.         } /* end while need a valid filename */
  1574.  
  1575.         printf("\nEnter description : ");
  1576.         GET_BUF();
  1577.  
  1578.         for ( wrk_ndx = 0, desc_len = 0, end_of_str = FALSE;
  1579.               wrk_ndx < 80; wrk_ndx++ )
  1580.         {
  1581.             if ( wrk_ndx < BUF_LEN )
  1582.             {
  1583.                 if ( buf[wrk_ndx] == '\n' ) /* End of inputted string?      */
  1584.                     end_of_str = TRUE;
  1585.                 if ( buf[wrk_ndx] == '\0' ) /* Overkill, End marked by \n   */
  1586.                     end_of_str = TRUE;
  1587.             }
  1588.             if ( end_of_str )
  1589.                 desc[wrk_ndx] = '\0';
  1590.             else
  1591.             {
  1592.                 desc[wrk_ndx] = buf[wrk_ndx];
  1593.                 desc_len++;
  1594.             }
  1595.         }
  1596.     } /* end else if command line arguments */
  1597.  
  1598. /*
  1599. **  Process the header of the .wav file.
  1600. */
  1601.     stat = process_header();
  1602.     if( stat == FAILURE )
  1603.         exit( 255 );
  1604.  
  1605.     PRINT( ("File : %s\n", input_path ) );
  1606.  
  1607.     memcpy( fsk_path, input_path, PATH_LEN );
  1608.     memcpy( &(fsk_path[STRLEN(fsk_path) - 3]), "fsk", 3 );
  1609.     memcpy( hex_path, input_path, PATH_LEN );
  1610.     memcpy( &(hex_path[STRLEN(hex_path) - 3]), "hex", 3 );
  1611.     memcpy( cas_path, input_path, PATH_LEN );
  1612.     memcpy( &(cas_path[STRLEN(cas_path) - 3]), "cas", 3 );
  1613.  
  1614.     if( fsk )
  1615.         fsk_file = fopen( (char *)fsk_path, "w" );
  1616.     hex_file = fopen( (char *)hex_path, "w" );
  1617.     cas_file = fopen( (char *)cas_path, "wb" );
  1618.  
  1619. /*
  1620. **  Write the header to the cassette file.  The header makes it possible
  1621. **  to identify the file as a .cas file.  Also, the description is stored
  1622. **  in this header record.
  1623. */
  1624.     memcpy( cas_rec.cas_record_id, "FUJI", 4 );
  1625.     cas_rec.cas_len_lo = desc_len;
  1626.     cas_rec.cas_len_hi = desc_len / 256;
  1627.     cas_rec.cas_aux1 = 0x00;
  1628.     cas_rec.cas_aux2 = 0x00;
  1629.     if( desc_len )
  1630.         memcpy( cas_rec.cas_data, desc, desc_len );
  1631.     fwrite( &cas_rec, 1, cas_rec.cas_len_hi * 256 + cas_rec.cas_len_lo + 8, cas_file );
  1632.  
  1633. /*
  1634. **  Write out default baud rate to the cassette file.
  1635. */
  1636.     memcpy( cas_rec.cas_record_id, "baud", 4 );
  1637.     cas_rec.cas_len_lo = 0;
  1638.     cas_rec.cas_len_hi = 0;
  1639.     cas_rec.cas_aux1 = 600 % 256;
  1640.     cas_rec.cas_aux2 = 600 / 256;
  1641.     fwrite( &cas_rec, 1, 8, cas_file );
  1642.  
  1643.  
  1644.     if( fsk )
  1645.         fprintf( fsk_file, "%.*s\n", desc_len, desc );
  1646.     fprintf( hex_file, "%.*s\n", desc_len, desc );
  1647.     fsk_print_first = TRUE;
  1648.  
  1649. /*
  1650. **      Process the data portion of the .wav file.
  1651. */
  1652.     stat = wav2fsk();
  1653.  
  1654.     cleanup();
  1655.  
  1656.     fprintf(stderr, "\nDone processing.\n");
  1657.  
  1658.     return 0;
  1659. }
  1660.  
  1661. /*****************************************************************************
  1662. **  MODIFICATION HISTORY
  1663. **
  1664. **  DATE        BY   Description
  1665. **  ----------  ---  ---------------------------------------------------------
  1666. **  1996/11/30  ERS  Project start
  1667. **  1997/05/01  ERS  Release 01.00
  1668. **
  1669. *****************************************************************************/
  1670.